package ms.unicorn.reasoning;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Random;

public class Simulator {

	public static FDGraph generateGraph(int scaleN, int refinementLevel) {
		FDGraph graph = new FDGraph("");
		graph.setAutoConnectToRoot(false);
		
		int h = refinementLevel;
		int l = Math.round(((float)scaleN)/h);
		
		FDNode[][] nodes = new FDNode[h][l];
		Random rnd = new Random();
		
		for (int i = h-1; i >= 0; i--)
			for (int j = 0; j<l; j++) {
				nodes[i][j] = graph.createNode(FDNode.FDNODE_REQUIREMENT, String.format("%d:%d", i, j));
				// create relation
				if (i < h-1) {
					//int r = Math.round(Math.max(l-1, Math.round(rnd.nextDouble() * l))) + 1;
					int r = rnd.nextInt(l) + 1;
					int childcount = l / r;
					for (int t = 1; t < r; t++) {
						FDNode compound = childcount > 1 ? graph.createNode(FDNode.FDNODE_COMPOUND, "") : nodes[i][j];
						if (childcount > 1) compound.addParentNode(nodes[i][j]);
						for(int c = 0; c < childcount; c++) {
							int idx = (t-1)*childcount + c;
							nodes[i+1][idx].addParentNode(compound);
						}
					}
					int last_childcount = l - (r-1)*childcount;
					int idx = (r-1)*childcount;
					FDNode compound = (last_childcount > 1) ? graph.createNode(FDNode.FDNODE_COMPOUND, ""): nodes[i][j];
					if (last_childcount > 1) compound.addParentNode(nodes[i][j]);
					for (int c = idx; c < l; c++)
						nodes[i+1][c].addParentNode(compound);
				}
			}
		
		FDNode compound = graph.createNode(FDNode.FDNODE_COMPOUND, "");
		compound.addParentNode(graph.getDummyRoot());
		
		for (int j = 0; j<l; j++)
			nodes[0][j].addParentNode(compound);
		return graph;
	}
	
	/**
	 * @param args
	 * @throws IOException 
	 * @throws ClassNotFoundException 
	 */
	public static void main(String[] args) throws IOException, ClassNotFoundException {
		System.out.println("n,h,ridx,ncount,d,t");
		int[] Scales = new int[] {500, 1000};
		for (int i = 0; i < Scales.length; i ++) 
			for (int h = 5; h <= 10; h++) 
				for (int idx = 1; idx <= 5; idx++) {
					String treename = String.format("hypergraphs/%d-%d-%d.obj", Scales[i], h, idx);
					File treefile = new File(treename);
					
					FDGraph graph;
					if (treefile.exists()) {
						FileInputStream fis = new FileInputStream(treefile);
					    ObjectInputStream ois = new ObjectInputStream(fis);
					    graph = (FDGraph) ois.readObject();
					    graph.propagateDAT();
					    ois.close();
					    fis.close();
					}
					else {
						graph = generateGraph(Scales[i], h);
						//long t = graph.propagateDAT();
						FileOutputStream fos = new FileOutputStream(treefile);
					    ObjectOutputStream oos = new ObjectOutputStream(fos);
					    oos.writeObject(graph);
					    oos.flush();
					    oos.close();
					    fos.close();
					}
					System.out.println(String.format("%d,%d,%d,%d,%f,%d",Scales[i], h, idx, graph.getNodes().size(), graph.getAverageDegree(), graph.getPropagationTime()));	
				}
		
	}

}
